package com.sweet.imserver.server;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.sweet.imserver.dao.DaoVerticle;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.Promise;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.eventbus.EventBus;
import io.vertx.core.http.HttpServerOptions;
import io.vertx.core.http.ServerWebSocket;
import io.vertx.core.impl.logging.Logger;
import io.vertx.core.impl.logging.LoggerFactory;
import io.vertx.core.json.JsonObject;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class IMServerVerticle extends AbstractVerticle {
  public static void main(String[] args) {
    Vertx.vertx().deployVerticle(new IMServerVerticle());
  }

  private final Logger LOGGER = LoggerFactory.getLogger(IMServerVerticle.class);

  private EventBus eventBus;
  private JwtAuthService jwtAuthService;

  private final Map<String, ServerWebSocket> socketMap = new ConcurrentHashMap<>();

  @Override
  public void start(Promise<Void> startPromise) throws Exception {
    jwtAuthService = new JwtAuthService(vertx);
    eventBus = vertx.eventBus();
    vertx.createHttpServer(new HttpServerOptions().setTcpKeepAlive(true)).webSocketHandler(serverWebSocket -> {
      final String socketId = serverWebSocket.textHandlerID();
      String path = serverWebSocket.path();
      String query = serverWebSocket.query();
      if (StrUtil.isBlank(query)) {
        serverWebSocket.close();
        return;
      }
      // token=
      LOGGER.debug("socket: " + socketId + ", path: " + path + ", query: " + query);
      String token = query.substring(6);
      jwtAuthService.authProvider.authenticate(new JsonObject().put("token", token))
        .onSuccess(user -> {
          LOGGER.debug("UserSocket连接: " + user.principal().encodePrettily());
          // 登录人id
          String mid = user.principal().getString("m");
          socketMap.put(mid, serverWebSocket);

          serverWebSocket.closeHandler(c -> {
            LOGGER.debug("socket close " + socketId);
          });

          serverWebSocket.handler(buf -> {
            LOGGER.debug("socketMsg: " + buf);
            sendMsg(buf, mid);
          });

          serverWebSocket.exceptionHandler(ex -> {
            LOGGER.error("socket: " + socketId + ", err", ex);
          });
        })
        .onFailure(err -> {
          LOGGER.error("token 过期");
          serverWebSocket.close();
        });


    }).listen(9098, res -> {
      if (res.succeeded()) {
        LOGGER.debug("IM Server Verticle 启动成功 端口：9098");
        startPromise.complete();
      } else {
        startPromise.fail(res.cause());
      }
    });
  }

  private void sendMsg(Buffer buffer, String mid) {
    JsonObject msgJson = buffer.toJsonObject();
    // 接收者
    String rid = msgJson.getString("rid");
    msgJson.put("id", IdUtil.getSnowflakeNextId() + "");
    msgJson.put("time", System.currentTimeMillis());
    msgJson.put("sid", mid);
    eventBus.send(DaoVerticle.SAVE_MSG_ADDRESS,  buffer.toJsonObject().put("sid", mid));
    ServerWebSocket serverWebSocket = socketMap.get(rid);
    if (serverWebSocket != null && !serverWebSocket.isClosed()) {
      serverWebSocket.writeTextMessage(msgJson.toString());
    }
  }
}
